package com.yvan.js;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.yvan.platform.YvanUtil;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.Undefined;
import lombok.val;

import java.io.IOException;

public class ScriptWrapperSerializer {

    public static void register() {
        // 注册 ScriptObjectMirror 序列化实现
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(ScriptObjectMirror.class, new ScriptObjectMirrorSerializer());
        YvanUtil.objectMapper.registerModule(simpleModule);

        // 注册 Undefined 序列化实现
        simpleModule = new SimpleModule();
        simpleModule.addSerializer(Undefined.class, new UndefinedSerializer());
        YvanUtil.objectMapper.registerModule(simpleModule);
    }

    /**
     * Undefined 序列化实现
     */
    public static class UndefinedSerializer extends JsonSerializer<Undefined> {
        @Override
        public void serialize(Undefined value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
            //gen.writeNull();
            gen.writeRaw("undefined");
        }
    }

    /**
     * ScriptObjectMirror 序列化实现
     */
    public static class ScriptObjectMirrorSerializer extends JsonSerializer<ScriptObjectMirror> {
        @Override
        public void serialize(ScriptObjectMirror value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
            val type = JQuery.$.type(value);
            if ("array".equals(type)) {
                gen.writeStartArray();
                val vs = value.values();
                for (val v : vs) {
                    if (v == null) {
                        serializers.getDefaultNullValueSerializer().serialize(v, gen, serializers);
                    } else {
                        serializers.findValueSerializer(v.getClass()).serialize(v, gen, serializers);
                    }
                }
                gen.writeEndArray();

            } else if ("object".equals(type)) {
                gen.writeStartObject();
                for (String key : value.getOwnKeys(true)) {
                    val v = value.get(key);
                    gen.writeFieldName(key);
                    if (v == null) {
                        serializers.getDefaultNullValueSerializer().serialize(v, gen, serializers);
                    } else {
                        serializers.findValueSerializer(v.getClass()).serialize(v, gen, serializers);
                    }
                }
                gen.writeEndObject();

            } else if ("function".equals(type)) {
                gen.writeObject(value.toString());

            } else if ("null".equals(type)) {
                gen.writeObject("null");

            } else {
                gen.writeObject(value.toString());
            }
        }
    }
}
